package cn.qiyu5522.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.qiyu5522.constant.SystemConstants;
import cn.qiyu5522.domain.VO.MenuRouteVO;
import cn.qiyu5522.domain.VO.MenuTreeVO;
import cn.qiyu5522.domain.VO.MenuVO;
import cn.qiyu5522.domain.entity.Menu;
import cn.qiyu5522.domain.entity.ResponseResult;
import cn.qiyu5522.domain.entity.SystemException;
import cn.qiyu5522.enums.AppHttpCodeEnum;
import cn.qiyu5522.mapper.MenuMapper;
import cn.qiyu5522.service.MenuService;
import cn.qiyu5522.service.RoleMenuService;
import cn.qiyu5522.service.RoleService;
import cn.qiyu5522.service.UserRoleService;
import cn.qiyu5522.utils.BeanCopyUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author Tonkey
 * @since 2024-04-22
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private RoleMenuService roleMenuService;

    @Resource
    private RoleService roleService;

    @Resource
    private MenuService menuService;


    @Override
    public List<String> selectPermsByUserId(Long id) {
        // 判断是否为管理员用户
        if(SystemConstants.SUPER_ADMINISTER_USER_ID.equals(id)){
            // 获取全部权限
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(Menu::getMenuType,SystemConstants.MENU,SystemConstants.BUTTON);
            queryWrapper.eq(Menu::getStatus,SystemConstants.MENU_NORMAL);
            List<String> perms = list(queryWrapper).stream().map(m->m.getPerms()).collect(Collectors.toList());
            return perms;
        }
        // 根据用户id 获取对应的角色id
        List<Long> roleIdListByUserId = userRoleService.selectRoleIdsByUserId(id);
        // 根据 角色 id 获取 菜单id
        List<Long> menuIds = roleMenuService.selectMenuIdsByRoleIds(roleIdListByUserId);
        // 根据菜单ID 获取 权限信息
        List<String> perms = menuService.selectPermsByMenuIds(menuIds);
        return perms;
    }

    @Override
    public List<String> selectPermsByMenuIds(List<Long> menuIds) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Menu::getId, menuIds);
        queryWrapper.in(Menu::getMenuType,SystemConstants.MENU,SystemConstants.BUTTON);
        queryWrapper.eq(Menu::getStatus,SystemConstants.MENU_NORMAL);
        List<Menu> menus = list(queryWrapper);
        List<String> perms = menus.stream().map(m -> m.getPerms()).collect(Collectors.toList());
        return perms;
    }

    @Override
    public List<Menu> selectMenusByUserId(Long id) {
        // 判断是否为管理员用户
        if(SystemConstants.SUPER_ADMINISTER_USER_ID.equals(id)){
            // 获取全部菜单
            LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Menu::getStatus,SystemConstants.MENU_NORMAL);
            // orderNum 降序排序
            queryWrapper.orderByAsc(Menu::getOrderNum);
            List<Menu> menus = list(queryWrapper);
            return menus;
        }
        // 根据用户id 获取对应的角色id
        List<Long> roleIdListByUserId = userRoleService.selectRoleIdsByUserId(id);
        // 根据 角色 id 获取 菜单id
        List<Long> menuIds = roleMenuService.selectMenuIdsByRoleIds(roleIdListByUserId);
        // 根据菜单ID 获取 菜单信息
        List<Menu> menus = menuService.selectMenusByMenuIds(menuIds);
        return menus;
    }

    @Override
    public List<Menu> selectMenusByMenuIds(List<Long> menuIds) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Menu::getId, menuIds);
        // orderNum 降序排序
        queryWrapper.orderByAsc(Menu::getOrderNum);
//        queryWrapper.in(Menu::getMenuType,SystemConstants.MENU,SystemConstants.BUTTON);
        queryWrapper.eq(Menu::getStatus,SystemConstants.MENU_NORMAL);
        List<Menu> menus = list(queryWrapper);
        return menus;
    }

    @Override
    public ResponseResult getList(String status, String menuName) {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.hasText(status),Menu::getStatus,status)
                .like(StringUtils.hasText(menuName),Menu::getMenuName,menuName);
        List<Menu> list = list(queryWrapper);
        // 转 vo
        List<MenuRouteVO> menuRouteVOS = BeanCopyUtils.copyBeanList(list, MenuRouteVO.class);
        return ResponseResult.okResult(menuRouteVOS);
    }

    @Override
    public ResponseResult addMenu(Menu menu) {
        save(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuById(Long id) {
        Menu menu = getById(id);
        MenuVO menuVO = BeanCopyUtils.copyBean(menu, MenuVO.class);
        return ResponseResult.okResult(menuVO);
    }

    @Override
    public ResponseResult updateMenu(Menu menu) {
        // 菜单的parentid 不能为自己
        if(menu.getId().equals(menu.getParentId())){
            throw new SystemException(AppHttpCodeEnum.UPDATE_OPERATE_ERROR.getCode(),"修改菜单："+menu.getMenuName()+" 失败，上级菜单不能选择自己");
        }
        updateById(menu);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult deleteMenuById(Long menuId) {
        // 	能够删除菜单，但是如果要删除的菜单有子菜单则提示：
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Menu::getParentId,menuId);
//        queryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
        List<Menu> list = list(queryWrapper);
        // 存在子菜单不允许删除 并且删除失败。
        if(ObjectUtil.isNotEmpty(list)){
            throw new SystemException(AppHttpCodeEnum.DELETE_OPERATE_ERROR.getCode()," 存在子菜单不允许删除");
        }
        removeById(menuId);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuTree() {
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(Menu::getOrderNum);
        // 查询全部菜单
        List<Menu> menus = menuService.list(queryWrapper);
        // 生成菜单树
        List<MenuTreeVO> menuTree = generateMenuTree(menus);

        return ResponseResult.okResult(menuTree);
    }

    @Override
    public ResponseResult roleMenuTreeSelect(Long roleId) {

        // 超级管理员返回全部 菜单
        if(SystemConstants.SUPER_ADMINISTER_ROLE_ID.equals(roleId)){
            List<Menu> list = list(null);
            List<MenuTreeVO> menuTree = generateMenuTree(list);
            return ResponseResult.okResult(menuTree);
        }

        List<Long> roleIds = new ArrayList<>();
        roleIds.add(roleId);
        // 查询 角色-菜单 中间表获取 菜单id
        List<Long> menuIds = roleMenuService.selectMenuIdsByRoleIds(roleIds);
        // 根据 menuIds 查询菜单信息
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Menu::getId,menuIds);
        List<Menu> list = list(queryWrapper);
        // 生成菜单树
        List<MenuTreeVO> menuTree = generateMenuTree(list);
        return ResponseResult.okResult(menuTree);
    }

    private List<MenuTreeVO> generateMenuTree(List<Menu> list) {
        // menu 实体 转 menuTreeVO
        List<MenuTreeVO> menuTreeVOS = BeanCopyUtils.copyBeanList(list, MenuTreeVO.class);
        // label 属性赋值
        List<MenuTreeVO> collect = menuTreeVOS.stream().map(m -> m.setLabel(m.getMenuName())).collect(Collectors.toList());
        // 构建菜单树
        // 返回的菜单树
        List<MenuTreeVO> menuTree = new ArrayList<>();
        // 1. 找出根节点菜单
        List<MenuTreeVO> rootMenus = collect.stream()
                .filter(menu -> SystemConstants.ROOT_MENU.equals(menu.getParentId()))
                .collect(Collectors.toList());
        // 2. 递归设置子菜单
        rootMenus.forEach(menuTreeVO -> {
            menuTreeVO.setChildren(getChildren(menuTreeVO.getId(), collect));
            menuTree.add(menuTreeVO);
        });
        return menuTree;
    }

    private List<MenuTreeVO> getChildren(Long parentId, List<MenuTreeVO> menuList) {
        // 获取子菜单
        List<MenuTreeVO> children = new ArrayList<>();
        for (MenuTreeVO menuTreeVO : menuList) {
            if (parentId.equals(menuTreeVO.getParentId())) {
                // 递归 设置子菜单
                menuTreeVO.setChildren(getChildren(menuTreeVO.getId(), menuList));
                children.add(menuTreeVO);
            }
        }
        return children;
    }
}
